#pragma once
#include <cstring>

namespace StringVariants {

  /**
   * @brief 简化版短字符串优化（SSO）实现。
   *
   *  - 当字符串长度不超过阈值时，直接存放在对象内的局部数组中。
   *  - 超出阈值后切换到堆分配模式，并保持追加操作的正确性。
   *  - 为便于讲解，未实现拷贝、移动等完整语义，适合 Benchmark 示例。
   */
  class SsoStringSimple {
  public:
    static constexpr std::size_t kLocalSize =
        sizeof(void *) == 8 ? 19 : 15; ///< 根据平台字长调整局部缓冲大小。

    /**
     * @brief 默认构造为空字符串，处于短字符串状态。
     */
    SsoStringSimple() : size_(0), is_short_(true) {
      local_[0] = '\0';
    }

    /**
     * @brief 通过 C 风格字符串初始化。
     *
     * @param s 输入字符串，若为 nullptr 则视为长度为 0。
     */
    explicit SsoStringSimple(const char *s) {
      std::size_t len = s ? std::strlen(s) : 0;
      if (len <= kLocalSize) {
        std::memcpy(local_, s ? s : "", len);
        local_[len] = '\0';
        size_ = len;
        is_short_ = true;
        heap_ = nullptr;
      } else {
        size_ = len;
        is_short_ = false;
        heap_ = new char[len + 1];
        std::memcpy(heap_, s, len + 1);
      }
    }

    /**
     * @brief 析构函数，若处于长字符串模式则释放堆内存。
     */
    ~SsoStringSimple() {
      if (!is_short_) delete[] heap_;
    }

    /**
     * @brief 追加单个字符，必要时在短/长模式之间切换。
     *
     * @param c 需要追加的字符。
     */
    void push_back(char c) {
      if (is_short_) {
        if (size_ < kLocalSize) {
          local_[size_++] = c;
          local_[size_] = '\0';
          return;
        }
        // 切换至堆模式并拷贝已有数据。
        char *new_heap = new char[size_ + 2];
        std::memcpy(new_heap, local_, size_);
        new_heap[size_] = c;
        new_heap[size_ + 1] = '\0';
        heap_ = new_heap;
        size_ += 1;
        is_short_ = false;
        return;
      }
      // 长字符串模式：重新分配以容纳新增字符。
      char *new_heap = new char[size_ + 2];
      std::memcpy(new_heap, heap_, size_);
      new_heap[size_] = c;
      new_heap[size_ + 1] = '\0';
      delete[] heap_;
      heap_ = new_heap;
      size_ += 1;
    }

    /**
     * @brief 获取 C 风格字符串视图。
     */
    const char *c_str() const { return is_short_ ? local_ : heap_; }

    /**
     * @brief 当前字符串长度。
     */
    std::size_t size() const { return size_; }

  private:
    union {
      char local_[kLocalSize + 1]; ///< 短字符串模式下的内嵌缓冲。
      char *heap_;                 ///< 长字符串模式下的堆指针。
    };
    std::size_t size_;             ///< 当前长度。
    bool is_short_;                ///< 是否处于短字符串模式。
  };

} // namespace StringVariants